package zheezes.protocol.impl.wt;

import java.lang.reflect.Modifier;

public abstract class DataUnit {
	protected DataId di = new DataId();
	protected boolean hasData = true;

	public DataUnit() {
		String name = getClass().getSimpleName();
		name = name.toLowerCase();
		int idx = name.indexOf("di");
		String distr = name.substring(idx + 2, idx + 6);
		di.setValue(distr);
	}
	
	public static DataUnit getDataUnit(byte ctrl, byte[] buf, int offset, int max) {
		// StringBuilder sb = new StringBuilder();
		DataUnit du = null;
		int idx = offset;
		String pack = String.format("%s.%du", DataUnit.class.getPackage().getName(), ctrl);
		String name = String.format("Ctrl%02XDi%02X%02XDataUnit", ctrl, buf[idx + 1], buf[idx]);
		idx += 2;
		try {
			Class clazz = Class.forName(String.format("%s.%s", pack, name));
			int modifiers = clazz.getModifiers();
			if (!Modifier.isAbstract(modifiers)) {
				du = (DataUnit) clazz.newInstance();
				/*idx += */du.setData(buf, idx, max); // no use to add
			}
		} catch(Exception e) {
		}
		return du;
	}

	public DataId getDataId() {
		return di;
	}
	
	public abstract int sizeOfData();

	public abstract int setData(byte[] buf, int offset, int max);

	public abstract int getData(byte[] buf, int offset);
	
	public byte[] getData() {
		byte[] buf = new byte[sizeOfData()];
		int len = getData(buf, 0);
		return buf.length == len ? buf : null;
	}
	
	public int size() {
		return sizeOfData() + 2;
	}

	public int setBytes(byte[] buf, int offset, int max) {
		int idx = offset;
		idx += di.setBytes(buf, idx, max);

		return setData(buf, idx, max);
	}

	public int getBytes(byte[] buf, int offset) {
		int idx = offset;
		idx += di.getBytes(buf, idx);
		if (hasData) {
			idx += getData(buf, idx);
		}

		return idx - offset;
	}
	
	public byte getCtrl() {
		String name = getClass().getSimpleName().toLowerCase();
		if(name.startsWith("ctrl")) {
			return Integer.valueOf(name.substring(4, 6), 16).byteValue();
		}
		return 0x00;
	}
}
